home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / bs941029.tgz / bbsx-941029.tar / bbsx / bbs_ufunc.c < prev    next >
C/C++ Source or Header  |  1994-10-29  |  56KB  |  2,282 lines

  1. #define _HPUX_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include <sys/time.h>
  9. #include <fcntl.h>
  10. #include <pwd.h>
  11. #include <termio.h>
  12. #include <sys/socket.h>
  13. #include <sys/stat.h>
  14. #include <dirent.h>
  15. #include <ndbm.h>
  16. #include <fnmatch.h>
  17.  
  18. #include "bbs.h"
  19. #include "buildsaddr.h"
  20. #include "strdup.h"
  21. #include "callvalid.h"
  22. #include "lockfile.h"
  23.  
  24.  
  25. /*---------------------------------------------------------------------------*/
  26.  
  27. void errorstop(int line)
  28. {
  29.   char buf[80];
  30.  
  31.   sprintf(buf, "Fatal error in line %d", line);
  32.   perror(buf);
  33.   fprintf(stderr, "Program stopped.\n");
  34.   free(alias_table);
  35.   exit(1);
  36. }
  37.  
  38. /*---------------------------------------------------------------------------*/
  39.  
  40. /* Use private function because some platforms are broken, eg 386BSD */
  41.  
  42. int Xtolower(int c)
  43. {
  44.   return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
  45. }
  46.  
  47. /*---------------------------------------------------------------------------*/
  48.  
  49. /* Use private function because some platforms are broken, eg 386BSD */
  50.  
  51. int Xtoupper(int c)
  52. {
  53.   return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c;
  54. }
  55.  
  56. /*---------------------------------------------------------------------------*/
  57.  
  58. char *strupc(char *s)
  59. {
  60.   char *p;
  61.  
  62.   for (p = s; *p = Xtoupper(*p); p++) ;
  63.   return s;
  64. }
  65.  
  66. /*---------------------------------------------------------------------------*/
  67.  
  68. char *strlwc(char *s)
  69. {
  70.   char *p;
  71.  
  72.   for (p = s; *p = Xtolower(*p); p++) ;
  73.   return s;
  74. }
  75.  
  76. /*---------------------------------------------------------------------------*/
  77.  
  78. int Strcasecmp(const char *s1, const char *s2)
  79. {
  80.   while (Xtolower(*s1) == Xtolower(*s2)) {
  81.     if (!*s1) return 0;
  82.     s1++;
  83.     s2++;
  84.   }
  85.   return Xtolower(*s1) - Xtolower(*s2);
  86. }
  87.  
  88. /*---------------------------------------------------------------------------*/
  89.  
  90. int Strncasecmp(const char *s1, const char *s2, int n)
  91. {
  92.   while (--n >= 0 && Xtolower(*s1) == Xtolower(*s2)) {
  93.     if (!*s1) return 0;
  94.     s1++;
  95.     s2++;
  96.   }
  97.   return n < 0 ? 0 : Xtolower(*s1) - Xtolower(*s2);
  98. }
  99.  
  100. /*---------------------------------------------------------------------------*/
  101.  
  102. char *strtrim(char *s)
  103. {
  104.   char *p;
  105.  
  106.   for (p = s; *p; p++) ;
  107.   while (--p >= s && isspace(*p & 0xff)) ;
  108.   p[1] = 0;
  109.   return s;
  110. }
  111.  
  112. /*---------------------------------------------------------------------------*/
  113.  
  114. const char *strcasepos(const char *str, const char *pat)
  115. {
  116.   const char *s, *p;
  117.  
  118.   for (; ; str++)
  119.     for (s = str, p = pat; ; s++, p++) {
  120.       if (!*p) return str;
  121.       if (!*s) return 0;
  122.       if (Xtolower(*s) != Xtolower(*p)) break;
  123.     }
  124. }
  125.  
  126. /*---------------------------------------------------------------------------*/
  127.  
  128. char *getstring(char *s)
  129. {
  130.  
  131.   char *p;
  132.   static int chr, lastchr;
  133.  
  134.   fflush(stdout);
  135.   alarm(1 * HOURS);
  136.   for (p = s; ; ) {
  137.     *p = 0;
  138.     lastchr = chr;
  139.     chr = getchar();
  140.     if (stopped) {
  141.       alarm(0);
  142.       clearerr(stdin);
  143.       *s = 0;
  144.       return s;
  145.     }
  146.     if (ferror(stdin) || feof(stdin)) {
  147.       alarm(0);
  148.       return 0;
  149.     }
  150.     switch (chr) {
  151.     case EOF:
  152.       alarm(0);
  153.       return (p == s) ? 0 : s;
  154.     case 0:
  155.       break;
  156.     case '\r':
  157.       alarm(0);
  158.       return s;
  159.     case '\n':
  160.       if (lastchr != '\r') {
  161.     alarm(0);
  162.     return s;
  163.       }
  164.       break;
  165.     default:
  166.       *p++ = chr;
  167.     }
  168.   }
  169. }
  170.  
  171. /*---------------------------------------------------------------------------*/
  172.  
  173. char *timestr(long gmt)
  174. {
  175.   static char buf[20];
  176.   struct tm *tm;
  177.  
  178.   tm = gmtime(&gmt);
  179.   sprintf(buf, "%02d%.3s%02d/%02d%02d",
  180.            tm->tm_mday,
  181.            monthnames + 3 * tm->tm_mon,
  182.            tm->tm_year % 100,
  183.            tm->tm_hour,
  184.            tm->tm_min);
  185.   return buf;
  186. }
  187.  
  188. /*---------------------------------------------------------------------------*/
  189.  
  190. char *rfc822_date(long gmt)
  191. {
  192.  
  193.   static char buf[32];
  194.   struct tm *tm;
  195.  
  196.   tm = gmtime(&gmt);
  197.   sprintf(buf, "%.3s, %d %.3s %02d %02d:%02d:%02d GMT",
  198.       daynames + 3 * tm->tm_wday,
  199.       tm->tm_mday,
  200.       monthnames + 3 * tm->tm_mon,
  201.       tm->tm_year % 100,
  202.       tm->tm_hour,
  203.       tm->tm_min,
  204.       tm->tm_sec);
  205.   return buf;
  206. }
  207.  
  208. /*---------------------------------------------------------------------------*/
  209.  
  210. long parse_date(const char *str)
  211. {
  212.  
  213.   char *p;
  214.   char monthstr[4];
  215.   long t;
  216.   struct tm tm;
  217.  
  218.   if (sscanf((char *) str,
  219.          "%*s %d %3s %d %d:%d:%d",
  220.          &tm.tm_mday,
  221.          monthstr,
  222.          &tm.tm_year,
  223.          &tm.tm_hour,
  224.          &tm.tm_min,
  225.          &tm.tm_sec) != 6) return -1;
  226.   if (strlen(monthstr) != 3) return -1;
  227.   p = strstr(monthnames, monthstr);
  228.   if (!p) return -1;
  229.   tm.tm_mon = (p - monthnames) / 3;
  230.   tm.tm_isdst = 0;
  231. #if defined __hpux || defined linux
  232.   t = mktime(&tm);
  233.   if (t != -1) return t - timezone;
  234. #elif defined sun
  235.   return timegm(&tm);
  236. #endif
  237.   return -1;
  238. }
  239.  
  240.  
  241. /*---------------------------------------------------------------------------*/
  242.  
  243. void make_parent_directories(const char *filename)
  244. {
  245.   char *p, dirname[1024];
  246.  
  247.   strcpy(dirname, filename);
  248.   p = strrchr(dirname, '/');
  249.   if (!p) halt();
  250.   *p = 0;
  251.   if (!mkdir(dirname, 0755)) return;
  252.  
  253.   if (errno != ENOENT) halt();
  254.   make_parent_directories(dirname);
  255.   if (mkdir(dirname, 0755)) halt();
  256. }
  257.  
  258. /*---------------------------------------------------------------------------*/
  259.  
  260. char *getfilename(int mesg)
  261. {
  262.   static char buf[12];
  263.   char cname[18];
  264.   char comm[50];
  265.   FILE *fp;
  266.  
  267.   sprintf(buf,
  268.       "%02x/%02x/%02x/%02x",
  269.       (mesg >> 24) & 0xff,
  270.       (mesg >> 16) & 0xff,
  271.       (mesg >>  8) & 0xff,
  272.       (mesg      ) & 0xff);
  273.   strcpy(cname,buf);
  274.   strcat(cname,compressext);   
  275.   if (fp=fopen(cname,"r"))
  276.   {
  277.     fclose(fp);
  278.     strcpy(comm,compress);
  279.     strcat(comm," ");strcat(comm,uncompressoption);strcat(comm," ");
  280.     strcat(comm,cname);
  281.     system(comm);
  282.   }      
  283.   return buf;
  284. }
  285.  
  286. /*---------------------------------------------------------------------------*/
  287.  
  288. void get_seq(void)
  289. {
  290.  
  291.   char buf[16];
  292.   char fname[1024];
  293.   struct flock flk;
  294.  
  295.   if (mode != BBS || is_tell_user) return;
  296.   sprintf(fname, "%s/%s", user.dir, SEQFILE);
  297. #ifdef __hpux
  298.   setresgid(user.gid, user.gid, 0);
  299.   setresuid(user.uid, user.uid, 0);
  300.   fdseq = open(fname, O_RDWR | O_CREAT, 0644);
  301.   setresuid(0, 0, 0);
  302.   setresgid(0, 0, 0);
  303. #else
  304.   setregid(0, user.gid);
  305.   setreuid(0, user.uid);
  306.   fdseq = open(fname, O_RDWR | O_CREAT, 0644);
  307.   setreuid(0, 0);
  308.   setregid(0, 0);
  309. #endif
  310.   if (fdseq < 0) halt();
  311.   flk.l_type = F_WRLCK;
  312.   flk.l_whence = SEEK_SET;
  313.   flk.l_start = 0;
  314.   flk.l_len = 0;
  315.   if (fcntl(fdseq, F_SETLK, &flk) == -1) {
  316.     if (level != MBOX)
  317.       puts("Sorry, you are already running another BBS.\n");
  318.     exit(1);
  319.   }
  320.   if (read(fdseq, buf, sizeof(buf)) >= 2) user.seq = atoi(buf);
  321. }
  322.  
  323. /*---------------------------------------------------------------------------*/
  324.  
  325. void put_seq(void)
  326. {
  327.  
  328.   char buf[16];
  329.   int n;
  330.  
  331.   if (mode != BBS || is_tell_user) return;
  332.   sprintf(buf, "%d\n", user.seq);
  333.   n = strlen(buf);
  334.   if (lseek(fdseq, 0L, SEEK_SET)) halt();
  335.   if (write(fdseq, buf, n) != n) halt();
  336. }
  337.  
  338. /*---------------------------------------------------------------------------*/
  339.  
  340. void wait_for_prompt(void)
  341. {
  342.  
  343.   char buf[1024];
  344.   int l;
  345.   FILE *dbfp;
  346.  
  347.   do {
  348.     if (!getstring(buf)) exit(1);
  349.  
  350.     l = strlen(buf);
  351.     if (*buf == '[') {
  352.        parse_command_line(buf);
  353.     }
  354.   } while (!l || buf[l-1] != '>');
  355. }
  356.  
  357. /*---------------------------------------------------------------------------*/
  358.  
  359. int get_index(int n, struct index *index)
  360. {
  361.  
  362.   int i1, i2, im;
  363.   long pos;
  364.  
  365.   i1 = 0;
  366.   if (lseek(fdindex, 0L, SEEK_SET)) halt();
  367.   if (read(fdindex, index, sizeof(struct index)) != sizeof(struct index)) return 0;
  368.   if (n == index->mesg) return 1;
  369.   if (n < index->mesg) return 0;
  370.  
  371.   if ((pos = lseek(fdindex, -sizeof(struct index), SEEK_END)) < 0) halt();
  372.   i2 = (int) (pos / sizeof(struct index));
  373.   if (read(fdindex, index, sizeof(struct index)) != sizeof(struct index)) halt();
  374.   if (n == index->mesg) return 1;
  375.   if (n > index->mesg) return 0;
  376.  
  377.   while (i1 + 1 < i2) {
  378.     im = (i1 + i2) / 2;
  379.     if (lseek(fdindex, im * sizeof(struct index), SEEK_SET) < 0) halt();
  380.     if (read(fdindex, index, sizeof(struct index)) != sizeof(struct index)) halt();
  381.     if (n == index->mesg) return 1;
  382.     if (n > index->mesg)
  383.       i1 = im;
  384.     else
  385.       i2 = im;
  386.   }
  387.   return 0;
  388. }
  389.  
  390. /*---------------------------------------------------------------------------*/
  391.  
  392. int read_allowed(const struct index *index)
  393. {
  394.   if (index->flags & DELETED) return 0;
  395.   if (level == ROOT) return 1;
  396.   if (index->to[1]) return 1;
  397.   return 0;
  398. }
  399.  
  400. /*---------------------------------------------------------------------------*/
  401.  
  402. char *get_user_from_path(char *path)
  403. {
  404.   char *cp;
  405.  
  406.   cp = strrchr(path, '!');
  407.   return cp ? (cp + 1) : path;
  408.   
  409. }
  410.  
  411. /*---------------------------------------------------------------------------*/
  412.  
  413. char *get_host_from_path(char *path)
  414. {
  415.  
  416.   char *cp;
  417.   static char tmp[1024];
  418.  
  419.   strcpy(tmp, path);
  420.   cp = strrchr(tmp, '!');
  421.   if (!cp) return myhostname;
  422.   *cp = 0;
  423.   cp = strrchr(tmp, '!');
  424.   return cp ? (cp + 1) : tmp;
  425. }
  426.  
  427. /*---------------------------------------------------------------------------*/
  428.  
  429. int msg_uniq(const char *bid, const char *mid)
  430. {
  431.  
  432.   DBM * bid_db;
  433.   datum datum_bid;
  434.   datum datum_offset;
  435.   long offset;
  436.   struct index index;
  437.  
  438.   datum_bid.dptr = (char *) bid;
  439.   datum_bid.dsize = strlen(bid);
  440.   if (!(bid_db = dbm_open(BID_DB, O_RDWR | O_CREAT, 0644))) halt();
  441.   datum_offset = dbm_fetch(bid_db, datum_bid);
  442.   dbm_close(bid_db);
  443.   if (!datum_offset.dptr) return 1;
  444.   memcpy((char *) &offset, datum_offset.dptr, sizeof(offset));
  445.   if (lseek(fdindex, offset, SEEK_SET) != offset) halt();
  446.   if (read(fdindex, &index, sizeof(struct index )) != sizeof(struct index )) halt();
  447.   if (strcmp(index.bid, bid)) halt();
  448.   return index.date < time((long *) 0) - 90 * DAYS;
  449. }
  450.  
  451.  
  452. /*---------------------------------------------------------------------------*/
  453.  
  454. void send_to_bbs(struct mail *mail)
  455. {
  456.  
  457.   DBM * bid_db;
  458.   FILE *fp;
  459.   datum datum_bid;
  460.   datum datum_offset;
  461.   struct index index;
  462.   struct strlist *p;
  463.   long offset;
  464.  
  465.   if (!*mail->subject) return;
  466.   if ((fdlock = lock_file(LOCKFILE, 0)) < 0) halt();
  467.   if (msg_uniq(mail->bid, mail->mid)) {
  468.     if (lseek(fdindex, -sizeof(struct index), SEEK_END) < 0)
  469.       index.mesg = 1;
  470.     else {
  471.       if (read(fdindex, &index, sizeof(struct index)) != sizeof(struct index)) halt();
  472.       index.mesg++;
  473.     }
  474.     index.date = mail->date;
  475.     index.lifetime_h = (mail->lifetime + 1) >> 8;
  476.     index.lifetime_l = (mail->lifetime + 1);
  477.     strcpy(index.bid, mail->bid);
  478.     strupc(index.bid);
  479.     strncpy(index.subject, mail->subject, LEN_SUBJECT);
  480.     index.subject[LEN_SUBJECT] = 0;
  481.     strncpy(index.to, get_user_from_path(mail->to), LEN_TO);
  482.     index.to[LEN_TO] = 0;
  483.     strupc(index.to);
  484.     strncpy(index.orig_to, get_user_from_path(mail->orig_to), LEN_TO);
  485.     index.orig_to[LEN_TO] = 0;
  486.     strupc(index.orig_to);
  487.     strncpy(index.at, get_host_from_path(mail->to), LEN_AT);
  488.     index.at[LEN_AT] = 0;
  489.     strupc(index.at);
  490.     strncpy(index.from, get_user_from_path(mail->from), LEN_FROM);
  491.     index.from[LEN_FROM] = 0;
  492.     strupc(index.from);
  493.     index.flags = 0;
  494.     index.size = 0;
  495. #ifdef BOXBIN    
  496.     if (mail->bin) {
  497.       index.flags |= BINARY;
  498.     }  
  499. #endif    
  500.     if (!(fp = fopen(getfilename(index.mesg), "w"))) {
  501.       make_parent_directories(getfilename(index.mesg));
  502.       if (!(fp = fopen(getfilename(index.mesg), "w"))) halt();
  503.     }
  504.     if (strcmp(index.to, "E") && strcmp(index.to, "M"))
  505.       for (p = mail->head; p; p = p->next) {
  506.     if (fputs(p->str, fp) == EOF) halt();
  507.     if (putc('\n', fp) == EOF) halt();
  508.     index.size += (strlen(p->str) + 1);
  509.       }
  510.     fclose(fp);
  511.     offset = lseek(fdindex, 0L, SEEK_END);
  512.     if (offset < 0) halt();
  513.     if (!(bid_db = dbm_open(BID_DB, O_RDWR | O_CREAT, 0644))) halt();
  514.     datum_bid.dptr = index.bid;
  515.     datum_bid.dsize = strlen(index.bid);
  516.     datum_offset.dptr = (char *) &offset;
  517.     datum_offset.dsize = sizeof(offset);
  518.     if (dbm_store(bid_db, datum_bid, datum_offset, DBM_REPLACE) < 0) halt();
  519.     dbm_close(bid_db);
  520.     if (write(fdindex, &index, sizeof(struct index)) != sizeof(struct index)) halt();
  521.     if (index.mesg == user.seq + 1) {
  522.       user.seq = index.mesg;
  523.       if (level != MBOX)
  524.         put_seq();
  525.     }
  526.   }
  527.   close(fdlock);
  528. }
  529.  
  530. /*---------------------------------------------------------------------------*/
  531.  
  532. void send_to_mail(struct mail *mail)
  533. {
  534.  
  535.   FILE *fp;
  536.   char command[1024];
  537.   int i;
  538.   struct strlist *p;
  539.  
  540.   switch (fork()) {
  541.   case -1:
  542.     halt();
  543.   case 0:
  544.     setgid(0);
  545.     setuid(0);
  546.     for (i = open_max() - 1; i >= 0; i--) close(i);
  547.     setsid();
  548.     fopen("/dev/null", "r+");
  549.     fopen("/dev/null", "r+");
  550.     fopen("/dev/null", "r+");
  551.     switch (fork()) {
  552.     case -1:
  553.       _exit(1);
  554.      case 0:
  555. #ifdef __386BSD__
  556.       sprintf(command, "/usr/sbin/sendmail -oi -oem -f %s %s", mail->from, mail->to);
  557. #else
  558.       sprintf(command, "/usr/lib/sendmail -oi -oem -f %s %s", mail->from, mail->to);
  559. #endif
  560.       if (!(fp = popen(command, "w"))) _exit(1);
  561.       fprintf(fp, "From: %s\n", mail->from);
  562.       fprintf(fp, "To: %s\n", mail->to);
  563.       fprintf(fp, "Date: %s\n", rfc822_date(mail->date));
  564.       if (*mail->subject) fprintf(fp, "Subject: %s\n", mail->subject);
  565.       fprintf(fp, "Message-ID: <%s>\n", mail->mid);
  566.       if (mail->lifetime != -1)
  567.     fprintf(fp, "Expires: %s\n", rfc822_date(mail->date + DAYS * mail->lifetime));
  568.       fprintf(fp, "Bulletin-ID: <%s>\n", mail->bid);
  569.       putc('\n', fp);
  570.       for (p = mail->head; p; p = p->next) {
  571.     fputs(p->str, fp);
  572.     putc('\n', fp);
  573.       }
  574.       pclose(fp);
  575.       _exit(0);
  576.     default:
  577.       _exit(0);
  578.     }
  579.   default:
  580.     wait((int *) 0);
  581.   }
  582. }
  583.  
  584. /*---------------------------------------------------------------------------*/
  585.  
  586. void send_to_news(struct mail *mail)
  587. {
  588.  
  589.   FILE *fp;
  590.   char *fromhost;
  591.   char *pp;
  592.   int fd;
  593.   int i;
  594.   struct strlist *p;
  595.  
  596.   if (!*mail->subject) return;
  597.   if ((fd = open("/usr/bin/rnews", O_RDONLY)) < 0) return;
  598.   close(fd);
  599.   switch (fork()) {
  600.   case -1:
  601.     halt();
  602.   case 0:
  603.     setgid(0);
  604.     setuid(0);
  605.     for (i = open_max() - 1; i >= 0; i--) close(i);
  606.     setsid();
  607.     fopen("/dev/null", "r+");
  608.     fopen("/dev/null", "r+");
  609.     fopen("/dev/null", "r+");
  610.     switch (fork()) {
  611.     case -1:
  612.       _exit(1);
  613.     case 0:
  614.       if (!(fp = popen("/usr/bin/rnews", "w"))) _exit(1);
  615.       fromhost = get_host_from_path(mail->from);
  616.       fprintf(fp, "From: %s@%s%s\n", get_user_from_path(mail->from), fromhost, strchr(fromhost, '.') ? "" : ".ampr.org");
  617.       fprintf(fp, "Date: %s\n", rfc822_date(mail->date));
  618.       fprintf(fp, "Newsgroups: ampr.bbs.%s\n", get_user_from_path(mail->to));
  619.       fprintf(fp, "Subject: %s\n", mail->subject);
  620.       fprintf(fp, "Message-ID: <%s>\n", mail->mid);
  621.       i = strlen(myhostname);
  622.       if (!strncmp(mail->from, myhostname, i) && mail->from[i] == '!')
  623.     pp = mail->from + i + 1;
  624.       else
  625.     pp = mail->from;
  626.       fprintf(fp, "Path: %s\n", pp);
  627.       if (mail->lifetime != -1)
  628.     fprintf(fp, "Expires: %s\n", rfc822_date(mail->date + DAYS * mail->lifetime));
  629.       fprintf(fp, "Distribution: %s\n", get_host_from_path(mail->to));
  630.       fprintf(fp, "Bulletin-ID: <%s>\n", mail->bid);
  631.       putc('\n', fp);
  632.       p = mail->head;
  633.       while (p && p->str[0] == 'R' && p->str[1] == ':')
  634.     p = p->next;
  635.       while (p &&
  636.       (p->str[0] == 'd' && p->str[1] == 'e' && p->str[2] == ' ' ||
  637.        p->str[0] == 't' && p->str[1] == 'o' && p->str[2] == ' '))
  638.     p = p->next;
  639.       while (p && p->str[0] == 0)
  640.     p = p->next;
  641.       while (p) {
  642.     fputs(p->str, fp);
  643.     putc('\n', fp);
  644.     p = p->next;
  645.       }
  646.       pclose(fp);
  647.       _exit(0);
  648.     default:
  649.       _exit(0);
  650.     }
  651.   default:
  652.     wait((int *) 0);
  653.   }
  654. }
  655.  
  656. /*---------------------------------------------------------------------------*/
  657.  
  658. void fix_address(char *addr)
  659. {
  660.  
  661.   char *p1, *p2;
  662.   char tmp[1024];
  663.   int c, skip;
  664.  
  665.   for (p1 = addr; *p1; p1++)
  666.     switch (*p1) {
  667.     case '%':
  668.       *p1 = '@';
  669.       break;
  670.     case ',':
  671.       *p1 = ':';
  672.       break;
  673.     case '^':
  674.       *p1 = '!';
  675.       break;
  676.     }
  677.  
  678.   while ((p1 = strchr(addr, '@')) && (p2 = strchr(p1, ':'))) {
  679.     *p1 = *p2 = 0;
  680.     sprintf(tmp, "%s%s!%s", addr, p1 + 1, p2 + 1);
  681.     strcpy(addr, tmp);
  682.   }
  683.  
  684.   while (p2 = strrchr(addr, '@')) {
  685.     *p2 = 0;
  686.     p1 = p2;
  687.     while (p1 > addr && *p1 != '!') p1--;
  688.     if (p1 == addr)
  689.       sprintf(tmp, "%s!%s", p2 + 1, addr);
  690.     else {
  691.       *p1 = 0;
  692.       sprintf(tmp, "%s!%s!%s", addr, p2 + 1, p1 + 1);
  693.     }
  694.     strcpy(addr, tmp);
  695.   }
  696.  
  697.   for (skip = 0, p1 = p2 = addr; c = *p1; p1++) {
  698.     if (c == '.' && fix_allowed)
  699.       skip = 1;
  700.     else if (c == '!')
  701.       skip = 0;
  702.     if (!skip) *p2++ = c;
  703.   }
  704.   *p2 = 0;
  705.  
  706.   if (!strchr(addr, '!')) {
  707.     sprintf(tmp, "%s!%s", myhostname, addr);
  708.     strcpy(addr, tmp);
  709.   }
  710.  
  711.   strlwc(addr);
  712. }
  713.  
  714. /*---------------------------------------------------------------------------*/
  715.  
  716. struct mail *alloc_mail(void)
  717. {
  718.   struct mail *mail;
  719.  
  720.   mail = calloc(1, sizeof(*mail));
  721.   mail->lifetime = -1;
  722.   return mail;
  723. }
  724.  
  725. /*---------------------------------------------------------------------------*/
  726.  
  727. void free_mail(struct mail *mail)
  728. {
  729.   struct strlist *p;
  730.  
  731.   while (p = mail->head) {
  732.     mail->head = p->next;
  733.     free(p);
  734.   }
  735.   free(mail);
  736. }
  737.  
  738. /*---------------------------------------------------------------------------*/
  739.  
  740. void route_mail(struct mail *mail)
  741. {
  742.  
  743. #define MidSuffix "@bbs.net"
  744.  
  745.   FILE *fp;
  746.   char *cp;
  747.   char *s;
  748.   char *tohost;
  749.   char *touser;
  750.   int n;
  751.   int fdbid;
  752.   struct strlist *p;
  753.  
  754.   /* Set date */
  755.  
  756.   mail->date = time((long *) 0);
  757.  
  758.   /* Fix addresses */
  759.  
  760.   fix_address(mail->from);
  761.   
  762.   fix_address(mail->to);
  763.   fix_address(mail->orig_to);
  764.   
  765.   /* Check for bogus mails */
  766.  
  767.   strtrim(mail->subject);
  768.   if ((cp = get_host_from_header(mail->subject)) && callvalid(cp)) goto Done;
  769.   if (level == MBOX && !packetcluster) {
  770.     cp = get_user_from_path(mail->to);
  771.     if (!cp) goto Done;
  772.     if (strlen(cp) > 1) {
  773.       if (!mail->head) goto Done;
  774.       cp = get_host_from_header(mail->head->str);
  775.       if (!cp || !calleq(cp, user.name)) goto Done;
  776.     }
  777.   }
  778.  
  779.   /* Set bid */
  780.  
  781.   if (!*mail->bid && (cp = strchr(mail->mid, '@')) && !strcmp(cp, MidSuffix)) {
  782.     strcpy(mail->bid, mail->mid);
  783.     mail->bid[strlen(mail->bid)-strlen(MidSuffix)] = 0;
  784.   }
  785.   if (!*mail->bid) {
  786.     n = 0;
  787.     if ((fdbid = lock_file(BIDFILE, 0)) < 0) halt();
  788.     if (fp = fopen(BIDFILE, "r")) {
  789.       fscanf(fp, "%d", &n);
  790.       fclose(fp);
  791.     }
  792.     n++;
  793.     if (!(fp = fopen(BIDFILE, "w")) || fprintf(fp, "%d\n", n) < 0) halt();
  794.     fclose(fp);
  795.     close(fdbid);
  796.     sprintf(mail->bid, "%012d", n);
  797.     strncpy(mail->bid, myhostname, strlen(myhostname));
  798.   }
  799.   mail->bid[LEN_BID] = 0;
  800.   strupc(mail->bid);
  801.  
  802.   /* Set mid */
  803.  
  804.   if (!*mail->mid) {
  805.     strcpy(mail->mid, mail->bid);
  806.     strcat(mail->mid, MidSuffix);
  807.   }
  808.  
  809.   /* Remove message delimiters */
  810.  
  811.   for (p = mail->head; p; p = p->next) {
  812.     s = p->str;
  813.     if (*s == '.' && !s[1]) *s = 0;
  814.     while (cp = strchr(s, '\004')) while (cp[0] = cp[1]) cp++;
  815.     while (cp = strchr(s, '\032')) while (cp[0] = cp[1]) cp++;
  816.     if (!Strncasecmp(s, "***end", 6)) *s = ' ';
  817.   }
  818.  
  819.   /* Call delivery agents */
  820.  
  821.   touser = get_user_from_path(mail->to);
  822.   tohost = get_host_from_path(mail->to);
  823.   if (callvalid(touser) || isvaliduser(touser)) {
  824.     send_to_mail(mail);
  825.   } else {
  826.     if (calleq(tohost, myhostname))
  827.       send_to_bbs(mail);
  828.     else if (callvalid(tohost))
  829.       send_to_mail(mail);
  830.     else
  831.       send_to_bbs(mail);
  832.     if (strcmp(touser, "e") && strcmp(touser, "m")) send_to_news(mail);
  833.   }
  834.  
  835.   /* Free mail */
  836.  
  837. Done:
  838.   free_mail(mail);
  839.  
  840. }
  841.  
  842. /*---------------------------------------------------------------------------*/
  843.  
  844. void append_line(struct mail *mail, char *line)
  845. {
  846.   struct strlist *p;
  847.  
  848.   p = malloc(sizeof(*p) + strlen(line));
  849.   p->next = 0;
  850.   strcpy(p->str, line);
  851.   if (!mail->head)
  852.     mail->head = p;
  853.   else
  854.     mail->tail->next = p;
  855.   mail->tail = p;
  856. }
  857.  
  858. /*---------------------------------------------------------------------------*/
  859.  
  860. int get_header_value(const char *name, int do822, char *line, char *value)
  861. {
  862.  
  863.   char *p1, *p2;
  864.   int c, comment;
  865.  
  866.   for (; *name; name++, line++)
  867.     if (Xtolower(*name) != Xtolower(*line)) return 0;
  868.  
  869.   if (do822) {
  870.     for (comment = 0, p1 = line; c = *p1; p1++) {
  871.       if (c == '(') comment++;
  872.       if (comment) *p1 = ' ';
  873.       if (comment && c == ')') comment--;
  874.     }
  875.     while ((p1 = strchr(line, '<')) && (p2 = strrchr(p1, '>'))) {
  876.       *p2 = 0;
  877.       line = p1 + 1;
  878.     }
  879.   }
  880.  
  881.   while (isspace(uchar(*line))) line++;
  882.   strcpy(value, strtrim(line));
  883.   return 1;
  884. }
  885.  
  886. /*---------------------------------------------------------------------------*/
  887.  
  888. char *get_host_from_header(const char *line)
  889. {
  890.  
  891.   char *p, *q;
  892.   static char buf[1024];
  893.  
  894.   if (*line == 'R' && line[1] == ':' && (p = strchr(strcpy(buf, line), '@'))) {
  895.     p++;
  896.     while (*p == ':' || isspace(uchar(*p))) p++;
  897.     for (q = p; isalnum(uchar(*q)); q++) ;
  898.     *q = 0;
  899.     return p;
  900.   }
  901.   return 0;
  902. }
  903.  
  904. /*---------------------------------------------------------------------------*/
  905.  
  906. int host_in_header(char *fname, char *host)
  907. {
  908.  
  909.   FILE *fp;
  910.   char buf[1024];
  911.   char *p;
  912.  
  913.   if (!(fp = fopen(fname, "r"))) halt();
  914.   while (fgets(buf, sizeof(buf), fp))
  915.     if ((p = get_host_from_header(buf)) && calleq(p, host)) {
  916.       fclose(fp);
  917.       return 1;
  918.     }
  919.   fclose(fp);
  920.   return 0;
  921. }
  922.  
  923. /*---------------------------------------------------------------------------*/
  924.  
  925. void dir_print(struct dir_entry *p)
  926. {
  927.   if (p) {
  928.     dir_print(p->left);
  929.     if (!stopped)
  930.       printf((dir_column++ % 5) < 4 ? "%5d %-8s" : "%5d %s\n", p->count, p->to);
  931.     dir_print(p->right);
  932.     free(p);
  933.   }
  934. }
  935.  
  936. /*---------------------------------------------------------------------------*/
  937.  
  938. void bbs(void)
  939. {
  940.  
  941.   FILE *fp;
  942.   char line[1024];
  943.   char buffer[1024], buf[1024], gen_prompt[1024], *p, *sl;
  944.   int k;
  945.   long l;
  946.   struct tm *tm;
  947.   char timestamp[11];
  948.  
  949.   if (level != MBOX) {
  950.     printf("BBSX  Revision: %s   Type ? for help.\n", BBSX_REVISION);
  951.     sprintf(line, "%s/%s", user.dir, HUSHFILE);
  952.     if (fp = fopen(line, "r")) {
  953.     fclose(fp);
  954.     } else
  955.       get_welcomemsg();
  956.   }  
  957.   if (level != MBOX && (fp = fopen(masterrcfile, "r"))) {
  958.     while (fgets(line, sizeof(line), fp)) parse_command_line(line);
  959.     fclose(fp);
  960.   }
  961.   sprintf(line, "%s/%s", user.dir, RCFILE);
  962.   if (fp = fopen(line, "r")) {
  963.     while (fgets(line, sizeof(line), fp)) parse_command_line(line);
  964.     fclose(fp);
  965.   }
  966.   if (doforward) {
  967.     connect_bbs(); 
  968.     wait_for_prompt();
  969.   }
  970.   if (level == MBOX) {
  971.      printf("[THEBOX-1.8-H$]");
  972.      if (has_passwd(user.name)) {
  973.        if (!doforward) {
  974.           l = time(0L);
  975.           tm = gmtime(&l);
  976.           sprintf(timestamp, "%02d%02d%02d%02d%02d",
  977.            tm->tm_mday,
  978.            tm->tm_mon + 1,
  979.            tm->tm_year % 100,
  980.            tm->tm_hour,
  981.            tm->tm_min);
  982.           get_passwd(user.name, timestamp, boxpassword);
  983.           printf(" %s\n", timestamp);
  984.           password_ok = 0;
  985.        } 
  986.        else  {
  987.          printf(" %s\n", boxpassword);
  988.        }   
  989.      } else
  990.      {
  991.         printf("\n");
  992.         *boxpassword = '\0';
  993.      }
  994.   } 
  995.   if (doforward) wait_for_prompt();
  996.   for (; ; ) {
  997.     if (doforward)
  998.       strcpy(line, "f>");
  999.     else {
  1000.       if (level == MBOX) 
  1001.         printf(">\n");
  1002.       else {
  1003.         *gen_prompt=0;
  1004.         if((p=strchr(prompt,'\\'))) {
  1005.           strncat(gen_prompt,prompt,p-prompt);
  1006.           do { 
  1007.             p++; 
  1008.             if(sl=strchr(p+1,'\\')) {
  1009.               strncpy(buf,p,sl-p);   
  1010.               buf[sl-p]=0;
  1011.             } else
  1012.               strcpy(buf,p);             
  1013.             switch(toupper(*p)) {
  1014.               case 'D' : l=time((long *) 0);
  1015.                          tm=localtime(&l);
  1016.                          sprintf(buffer,"%02d.%02d.%02d",
  1017.                                          tm->tm_mday,
  1018.                                          tm->tm_mon,
  1019.                                          tm->tm_year % 100);
  1020.                        strcat(gen_prompt,buffer);
  1021.                        strcat(gen_prompt,&buf[1]);
  1022.                        break;
  1023.                        
  1024.               case 'N' : strcat(gen_prompt,"\n");
  1025.                         strcat(gen_prompt,&buf[1]);
  1026.                          break;
  1027.                          
  1028.               case 'W' : strcat(gen_prompt,last_board);
  1029.                        strcat(gen_prompt,&buf[1]);
  1030.                          break;
  1031.                          
  1032.               case 'U' : strcpy(buffer,user.name);
  1033.                        strupc(buffer);
  1034.                        strcat(gen_prompt,buffer);
  1035.                        strcat(gen_prompt,&buf[1]);
  1036.                        break;
  1037.                        
  1038.               case 'H' : strcpy(buffer,myhostname);
  1039.                        strupc(buffer);
  1040.                        strcat(gen_prompt,buffer);
  1041.                        strcat(gen_prompt,&buf[1]);
  1042.                        break;
  1043.                        
  1044.               case 'T' : l=time((long *) 0);
  1045.                          tm=localtime(&l);
  1046.                          sprintf(buffer,"%02d:%02d",tm->tm_hour,tm->tm_min);
  1047.                        strcat(gen_prompt,buffer);
  1048.                        strcat(gen_prompt,&buf[1]);
  1049.                        break;
  1050.                        
  1051.               case '\\': strcat(gen_prompt,"\\");
  1052.                        strcat(gen_prompt,&buf[1]);
  1053.                        p++;
  1054.                        break;
  1055.               case '1':
  1056.               case '2':
  1057.               case '3':
  1058.               case '4':
  1059.               case '5':
  1060.               case '6':
  1061.               case '7':
  1062.               case '0': sscanf(buf,"%o",&k);
  1063.                         if(k > 0 && k < 256)
  1064.                           strncat(gen_prompt,(char *) &k, 1);
  1065.                         sl=buf;
  1066.                         while(*sl && (
  1067.                               *sl == '1' ||
  1068.                               *sl == '2' ||
  1069.                               *sl == '3' ||
  1070.                               *sl == '4' ||
  1071.                               *sl == '5' ||
  1072.                               *sl == '6' ||
  1073.                               *sl == '7' ||
  1074.                               *sl == '0')) sl++;
  1075.                         if (*sl) strcat(gen_prompt,sl);      
  1076.                         break;   
  1077.               default:  strcat(gen_prompt,"\\");
  1078.                         strcat(gen_prompt,buf);
  1079.                         break;
  1080.             }
  1081.             while(*p != '\\' && *p) p++;
  1082.           } while(strchr(p,'\\'));           
  1083.         } else
  1084.           strcpy(gen_prompt,prompt);
  1085.         printf("%s",gen_prompt);   
  1086.       }  
  1087.       if (!getstring(line)) exit(1);
  1088.     }
  1089.     parse_command_line(line);
  1090.     doforward = 0;
  1091.     if (stopped) {
  1092.       puts("\n*** Interrupt ***");
  1093.       stopped = 0;
  1094.     }
  1095.   }
  1096. }
  1097.  
  1098. /*---------------------------------------------------------------------------*/
  1099.  
  1100. void interrupt_handler(int sig)
  1101. {
  1102.   static struct termio save;
  1103.   
  1104.   signal(sig, interrupt_handler);
  1105.   
  1106.   ioctl(0,TCGETA, &save);
  1107.   save.c_cc[VINTR] = orig_escape;
  1108.   ioctl(0,TCSETA, &save);
  1109.   
  1110.   stopped = 1;
  1111. }
  1112.  
  1113. /*---------------------------------------------------------------------------*/
  1114.  
  1115. void alarm_handler(int sig)
  1116. {
  1117.   puts("\n*** Timeout ***");
  1118.   exit(1);
  1119. }
  1120.  
  1121. /*---------------------------------------------------------------------------*/
  1122.  
  1123. void recv_from_mail_or_news(void)
  1124. {
  1125.  
  1126.   char *cp;
  1127.   char distr[1024];
  1128.   char expire[1024];
  1129.   char line[1024];
  1130.   int from_priority;
  1131.   int n;
  1132.   int state;
  1133.   struct mail *mail;
  1134.  
  1135.   while (fgets(line, sizeof(line), stdin)) {
  1136.     mail = alloc_mail();
  1137.     *distr = 0;
  1138.     *expire = 0;
  1139.     from_priority = 0;
  1140.     state = 0;
  1141.     n = strncmp(line, "#! rnews ", 9) ? 0x7fffffff : atoi(line + 9);
  1142.     for (; ; ) {
  1143.       switch (state) {
  1144.       case 0:
  1145.     if (*line) {
  1146.       if (from_priority < 1 && !strncmp(line, "From ", 5) && sscanf(line, "From %s", mail->from) == 1)
  1147.         from_priority = 1;
  1148.       if (from_priority < 2 && get_header_value("Path:", 1, line, mail->from))
  1149.         from_priority = 2;
  1150.       if (from_priority < 3 && get_header_value("From:", 1, line, mail->from))
  1151.         from_priority = 3;
  1152.       get_header_value("Newsgroups:", 1, line, mail->to);
  1153.       get_header_value("Subject:", 0, line, mail->subject);
  1154.       get_header_value("Message-ID:", 1, line, mail->mid);
  1155.       get_header_value("Distribution:", 1, line, distr);
  1156.       get_header_value("Expires:", 1, line, expire);
  1157.       get_header_value("Bulletin-ID:", 1, line, mail->bid);
  1158.     } else
  1159.       state = 1;
  1160.     break;
  1161.       case 1:
  1162.     if (!*line) break;
  1163.     state = 2;
  1164.       case 2:
  1165.     append_line(mail, line);
  1166.       }
  1167.       if (n <= 0 || !fgets(line, sizeof(line), stdin)) break;
  1168.       n -= strlen(line);
  1169.       strtrim(line);
  1170.     }
  1171.     if (*mail->to && from_priority && state == 2) {
  1172.       if (!strncmp(mail->to, "ampr.bbs.", 9)) strcpy(mail->to, mail->to + 9);
  1173.       if (cp = strchr(mail->to, ',')) *cp = 0;
  1174.       if (cp = strrchr(mail->to, '.')) strcpy(mail->to, cp + 1);
  1175.       if (cp = strchr(distr, ',')) *cp = 0;
  1176.       if (cp = strrchr(distr, '.')) strcpy(distr, cp + 1);
  1177.       if (*distr) {
  1178.     strcat(mail->to, "@");
  1179.     strcat(mail->to, distr);
  1180.       }
  1181.       if (*expire) {
  1182.     mail->lifetime = parse_date(expire);
  1183.     if (mail->lifetime != -1) {
  1184.       mail->lifetime = (mail->lifetime - time((long *) 0)) / DAYS;
  1185.       if (mail->lifetime < 1) mail->lifetime = 1;
  1186.     }
  1187.       }
  1188.       strcpy(mail->orig_to, mail->to);
  1189.       route_mail(mail);
  1190.     }
  1191.   }
  1192. }
  1193.  
  1194. /*---------------------------------------------------------------------------*/
  1195.  
  1196. int forward_allowed(const struct index *index,const char *name)
  1197. {
  1198.   FILE *fp;
  1199.   char fname[50];
  1200.   char line[80];
  1201.   char cmp[80],cmd[80],tmp[80], junk[1024];
  1202.   int param;
  1203.  
  1204.   strcpy(fname,name);
  1205.   strcat(fname,".NO");
  1206.   if (fp=fopen(fname,"r"))
  1207.   {              
  1208.     while (!feof(fp))    
  1209.     {
  1210.       fgets(line,80,fp);
  1211.       *cmd = 0; *cmp = 0; *junk = 0;
  1212.       param=sscanf(line,"%[><@]%s%s",cmd,cmp,junk);
  1213.       if (param > 1) {
  1214.         switch(*cmd) {
  1215.           case '>' : strcpy(tmp,index->to);
  1216.                      break; 
  1217.           case '@' : strcpy(tmp,index->at);
  1218.                      break;
  1219.           case '<' : strcpy(tmp,index->from);
  1220.                      break;
  1221.         }
  1222.         strupc(tmp);strupc(cmp);
  1223.         if (fnmatch(cmp, tmp, FNM_CASEFOLD) != FNM_NOMATCH) {
  1224.           fclose(fp);
  1225.           return 0;
  1226.         }
  1227.       }  
  1228.     }
  1229.     fclose(fp);
  1230.   }
  1231.   return 1;  
  1232. }
  1233.  
  1234. /*---------------------------------------------------------------------------*/
  1235.  
  1236. int send_allowed(const struct mail *mail, const char *at, const char *name)
  1237. {
  1238.   FILE *fp;
  1239.   char fname[50];
  1240.   char line[80];
  1241.   char cmp[80],cmd[80],tmp[80], junk[1024];
  1242.   int param;
  1243.  
  1244.   strcpy(fname,name);
  1245.   strcat(fname,".NO");
  1246.   if (fp=fopen(fname,"r"))
  1247.   {              
  1248.     while (!feof(fp)) {
  1249.       fgets(line,80,fp);
  1250.       *cmd = 0; *cmp = 0; *junk = 0;
  1251.       param=sscanf(line,"%[><@]%s%s",cmd,cmp,junk);
  1252.       if (param > 1) {
  1253.         switch(*cmd) {
  1254.           case '>' : strcpy(tmp,mail->to);
  1255.                      break; 
  1256.           case '@' : strcpy(tmp,at);
  1257.                      break;
  1258.           case '<' : strcpy(tmp,mail->from);
  1259.                      break;
  1260.         }
  1261.         strupc(tmp);strupc(cmp);
  1262.         if (fnmatch(cmp, tmp, FNM_CASEFOLD) != FNM_NOMATCH) {
  1263.           fclose(fp);
  1264.           return 0;
  1265.         }  
  1266.       }
  1267.     }
  1268.     fclose(fp);
  1269.   }
  1270.   return 1;
  1271. }
  1272.  
  1273. /*---------------------------------------------------------------------------*/
  1274.  
  1275. void getalias(char *original)                               
  1276. {
  1277.   char line[1024];
  1278.   char path[1024];
  1279.   FILE *fp;
  1280.   short param;
  1281.   char alias[80], change[80], junk[1024];
  1282.  
  1283.   if (fp=fopen(ALIASFILE,"r")) {
  1284.     if (!callvalid(get_user_from_path(original))){  
  1285.       while(!(feof(fp))){
  1286.         fgets(line,80,fp);
  1287.         param=sscanf(line,"%s%s%s",alias, change, junk);
  1288.         if (*alias != '#' && param > 1) {
  1289.           strupc(alias);
  1290.           strupc(change);
  1291.           strupc(original);
  1292.           if (fnmatch(alias, original, FNM_CASEFOLD) != FNM_NOMATCH) {
  1293.             strcpy(original, change);
  1294.             original[8] = '\0';
  1295.             fclose(fp);
  1296.             return ;
  1297.           } 
  1298.         }
  1299.       }
  1300.     }
  1301.     fclose(fp);
  1302.   }  
  1303.   else
  1304.     return ;
  1305. }
  1306.  
  1307.  
  1308. /*---------------------------------------------------------------------------*/
  1309.           
  1310. int read_config()
  1311. {
  1312.   FILE *fp;
  1313.   static char line[1024];
  1314.   char cmd[1024];
  1315.   char buf[1024];
  1316.   char *s;
  1317.   int i;
  1318.  
  1319.   gethostname(myhostname,16);
  1320.  
  1321.   if (fp = fopen(CONFIGFILE, "r")) {
  1322.     while (fgets(line, sizeof(line), fp)) {
  1323.       *cmd=0;
  1324.       if (sscanf(line,"%s\n",cmd)) {
  1325.         if (*cmd != '#') {
  1326.           if (!Strncasecmp(cmd, "cext",4)) {
  1327.             if (sscanf(line,"%s %s\n",cmd, compressext) < 2) {
  1328.               halt();
  1329.             }
  1330.           } else
  1331.           if (!Strncasecmp(cmd, "cprg",4)) {
  1332.             if (sscanf(line,"%s %s\n",cmd, compress) < 2) {
  1333.               halt();
  1334.             }
  1335.           } else 
  1336.           if (!Strncasecmp(cmd, "uncom",4)) {
  1337.             if (sscanf(line,"%s %s\n",cmd, uncompressoption) < 2) {
  1338.               halt();
  1339.             }
  1340.           } else
  1341.           if (!Strncasecmp(cmd, "compressopt",9)) {
  1342.             if (sscanf(line,"%s %s\n",cmd, compressoption) < 2) {
  1343.               halt();
  1344.             }
  1345.           } else
  1346.           if (!Strncasecmp(cmd, "bbsadm",6)) {
  1347.             if (sscanf(line,"%s %s\n",cmd, bbsadm) < 2) {
  1348.               halt();
  1349.             }
  1350.           } else
  1351.           if (!Strncasecmp(cmd, "telluser",4)) {
  1352.             if (sscanf(line,"%s %s\n",cmd, telluser) < 2) {
  1353.               halt();
  1354.             }
  1355.           } else
  1356.           if (!Strncasecmp(cmd, "mydomain",6)) {
  1357.             if (sscanf(line,"%s %s\n",cmd, mydomain) < 2) {
  1358.               halt();
  1359.             }
  1360.           } else
  1361.           if (!Strncasecmp(cmd, "myhostname",6)) {
  1362.             if (sscanf(line,"%s %s\n",cmd, myhostname) < 2) {
  1363.               halt();
  1364.             }
  1365.             strcpy(Myhostname,myhostname);
  1366.             strupc(Myhostname);
  1367.           } else
  1368.           if (!Strncasecmp(cmd, "logging",6)) {
  1369.             if (sscanf(line,"%s %s\n",cmd, buf) < 2) {
  1370.               halt();
  1371.             }
  1372.             log_reading = (toupper(*buf) == 'Y'); 
  1373.           } else
  1374.           if (!Strncasecmp(cmd, "debug",5)) {
  1375.             if (sscanf(line,"%s %s\n",cmd, buf) < 2) {
  1376.               halt();
  1377.             }
  1378.             debug = (toupper(*buf) == 'Y'); 
  1379.           } else
  1380.           if (!Strncasecmp(cmd, "fixaddress",5)) {
  1381.             if (sscanf(line,"%s %s\n",cmd, buf) < 2) {
  1382.               halt();
  1383.             }
  1384.             fix_allowed = !(toupper(*buf) == 'N'); 
  1385.           } else
  1386.           if (!Strncasecmp(cmd, "list",4)) {
  1387.             if (sscanf(line,"%s %d\n",cmd, &max_list) < 2) {
  1388.               halt();
  1389.             }
  1390.           } else
  1391.           if (!Strncasecmp(cmd, "debugfile",6)) {
  1392.             if (sscanf(line,"%s %s\n",cmd, debugfile) < 2) {
  1393.               halt();
  1394.             }
  1395.           } else
  1396.           if (!Strncasecmp(cmd, "helpfile",6)) {
  1397.             if (sscanf(line,"%s %s\n",cmd, helpfile) < 2) {
  1398.               halt();
  1399.             }
  1400.           } else
  1401.           if (!Strncasecmp(cmd, "infofile",6)) {
  1402.             if (sscanf(line,"%s %s\n",cmd, infofile) < 2) {
  1403.               halt();
  1404.             }
  1405.           } else
  1406.           if (!Strncasecmp(cmd, "masterrcfile",6)) {
  1407.             if (sscanf(line,"%s %s\n",cmd, masterrcfile) < 2) {
  1408.               halt();
  1409.             }
  1410.           } else
  1411.           if (!Strncasecmp(cmd, "mailfile",6)) {
  1412.             if (sscanf(line,"%s %s\n",cmd, mailfile) < 2) {
  1413.               halt();
  1414.             }
  1415.           } else
  1416.           if (!Strncasecmp(cmd, "station",6)) {
  1417.             i=sscanf(line,"%s %s\n",cmd, buf); 
  1418.             if (i == 1) {
  1419.               *station = 0;
  1420.             } else
  1421.             {
  1422.               s=strchr(line, '[');
  1423.               if (s) {
  1424.                strcpy(station,s);
  1425.                station[strlen(station)-1]=0;
  1426.               } else
  1427.               {
  1428.                 *station = 0;
  1429.               }  
  1430.             }  
  1431.           } 
  1432.         }
  1433.       }
  1434.     }
  1435.     fclose(fp);
  1436.   }
  1437.   else {
  1438.     halt();
  1439.   } 
  1440.   
  1441.   strcpy(Myhostname,myhostname);
  1442.   strupc(Myhostname); 
  1443. }
  1444.  
  1445. /*---------------------------------------------------------------------------*/
  1446.  
  1447. void init_aliasdb(void) 
  1448. {
  1449.  
  1450.   const struct cmdtable *cmdp;
  1451.   struct aliastable *p, *new;
  1452.   
  1453.   if ((alias_table=malloc(sizeof(struct aliastable))) == NULL) halt();
  1454.   p=alias_table;
  1455.   cmdp=cmdtable;
  1456.   
  1457.   strcpy(alias_table->orig,cmdp->name);
  1458.   strcpy(alias_table->alias,cmdp->name);
  1459.   strupc(alias_table->orig);
  1460.   strupc(alias_table->alias);
  1461.   alias_table->is_std = 1;
  1462.   alias_table->level=cmdp->level;
  1463.   alias_table->next = NULL;
  1464.   cmdp++;
  1465.  
  1466.   for(; cmdp->name; cmdp++) {
  1467.     insert_alias(cmdp->name, cmdp->name, cmdp->level, 1);
  1468.   }
  1469. }    
  1470.  
  1471. /*---------------------------------------------------------------------------*/
  1472.  
  1473. void get_welcomemsg(void)
  1474. {
  1475.   char line[1024];
  1476.   FILE *fp;
  1477.   
  1478.   if (fp = fopen(WELCOMEMSG, "r")) {
  1479.     while (fgets(line,sizeof(line),fp)) printf(line);
  1480.     fclose(fp);
  1481.   }
  1482.   
  1483.   return;
  1484. }  
  1485.  
  1486. /*---------------------------------------------------------------------------*/
  1487.  
  1488. void insert_alias(const char *orig, const char *alias, 
  1489.                   const int level, char is_std)
  1490. {
  1491.    struct aliastable *p, *ins, *new;
  1492.    char u_orig[256];
  1493.    char u_alias[256];
  1494.  
  1495.    strcpy(u_orig,orig);
  1496.    strcpy(u_alias,alias);
  1497.    strupc(u_orig);
  1498.    strupc(u_alias);
  1499.    ins=p=alias_table;
  1500.    while(p && (strcmp(p->orig,u_orig) < 0)) {
  1501.       ins=p;
  1502.       p=p->next;
  1503.    }
  1504.    if (!strcmp(p->orig,u_orig)) {
  1505.      strcpy(p->alias,u_alias);
  1506.      p->is_std=0;
  1507.      p->level=0;
  1508.      return;
  1509.    }    
  1510.    if ((new=malloc(sizeof(struct aliastable))) == NULL) halt();
  1511.    new->next = p;
  1512.    strcpy(new->orig,u_orig);
  1513.    strcpy(new->alias,u_alias);
  1514.    new->is_std = is_std;
  1515.    new->level = level;
  1516.    ins->next = new;
  1517.    
  1518.    return;
  1519. }
  1520.  
  1521.  
  1522. /*---------------------------------------------------------------------------*/
  1523.  
  1524. void forward_message(const struct index *index, const char *filename, 
  1525.                      const char *at, int skip_header)
  1526. {
  1527.  
  1528.   FILE * fp, * dbfp;
  1529.   char buf[1024];
  1530.   char buf1[1024];
  1531.   int c;
  1532.   int lifetime;
  1533.   struct tm *tm;
  1534.  
  1535.   lifetime = ((index->lifetime_h << 8) & 0xff00) + (index->lifetime_l & 0xff) - 1;
  1536.   if (!forward_allowed(index, user.name))  
  1537.     return;
  1538.  
  1539.   if (lifetime != -1)
  1540.     sprintf(buf,"S %s%s%s < %s%s%s # %d",
  1541.        index->orig_to,
  1542.        *index->at ? " @ " : "",
  1543.            at,
  1544.        index->from,
  1545.        *index->bid ? " $" : "",
  1546.        index->bid,
  1547.        lifetime);
  1548.   else
  1549.     sprintf(buf,"S %s%s%s < %s%s%s",
  1550.        index->orig_to,
  1551.        *index->at ? " @ " : "",
  1552.            at,
  1553.        index->from,
  1554.        *index->bid ? " $" : "",
  1555.        index->bid);
  1556.  
  1557.   if (subject_in_send) {
  1558.     strcpy(buf1,buf);
  1559.     if (!strcmp(index->to, "E") || !strcmp(index->to, "M")) 
  1560.       sprintf(buf,"%s %s%s\032",buf1, index->subject, 
  1561.                                 strcmp(index->to,"M") ? " " : "          ");
  1562.   }
  1563.   puts(buf);
  1564.   
  1565.   if (debug) {
  1566.     if ((fdlock = lock_file(LOCKFILE, 0)) < 0) halt();
  1567.     dbfp= fopen(debugfile,"a");
  1568.     fprintf(dbfp,"F> %s: %s\n",user.name, buf);
  1569.     fclose(dbfp);
  1570.     close(fdlock);
  1571.   }
  1572.   
  1573.   if (!getstring(buf)) exit(1);
  1574.   
  1575.   if (debug) {
  1576.     if ((fdlock = lock_file(LOCKFILE, 0)) < 0) halt();
  1577.     dbfp= fopen(debugfile,"a");
  1578.     fprintf(dbfp,"%s: %s\n",user.name, buf);
  1579.     fclose(dbfp);
  1580.     close(fdlock);
  1581.   }
  1582.   
  1583.   switch (*buf) {
  1584.     case 'O':
  1585.     case 'o':
  1586.       if ((!strcmp(index->to, "E") || !strcmp(index->to, "M"))) {  
  1587.         if(!subject_in_send)
  1588.           puts(*index->subject ? index->subject : "no subject");
  1589.         wait_for_prompt();
  1590.         break; 
  1591.       }  
  1592.       else{
  1593.          puts(*index->subject ? index->subject : "no subject");
  1594.        fflush(stdout);
  1595.        tm = gmtime(&index->date);
  1596.        printf("R:%02d%02d%02d/%02d%02dz @%s.%s %s\n",
  1597.            tm->tm_year % 100,
  1598.            tm->tm_mon + 1,
  1599.            tm->tm_mday,
  1600.            tm->tm_hour,
  1601.            tm->tm_min,
  1602.            Myhostname,
  1603.            mydomain,
  1604.                    station);
  1605.        if (!(fp = fopen (filename, "r"))) halt();
  1606.        if (skip_header)
  1607.        while (fgets(buf, sizeof(buf), fp) && *buf != '\n') ;
  1608.        while ((c = getc(fp)) != EOF) putchar(c);
  1609.        fclose(fp);
  1610.       }
  1611.     
  1612.       puts("\032");
  1613.       wait_for_prompt();
  1614.       break;
  1615.       
  1616.   case 'N':
  1617.   case 'n':
  1618.     wait_for_prompt();
  1619.     break;
  1620.     
  1621.   case '>':  
  1622.     if ((!strcmp(index->to, "E") || !strcmp(index->to, "M"))) 
  1623.       break;
  1624.     else
  1625.       exit(1);
  1626.         
  1627.   default:
  1628.     exit(1);
  1629.   }
  1630. }
  1631.  
  1632. /*---------------------------------------------------------------------------*/
  1633.  
  1634. int get_lowest_mesg(int argc, char **argv) {
  1635.  
  1636.   int i,j;
  1637.   struct index index;
  1638.   int lowest=999999; 
  1639.  
  1640.   for (i = 1; i < argc; i++) {
  1641.     j = atoi(argv[i]);
  1642.     if (j && (*argv[i-1] != '-')) { 
  1643.       if (j > lowest_on_start) {
  1644.         if (j  < lowest) {
  1645.           lowest = j;
  1646.         }  
  1647.       } else
  1648.         lowest = lowest_on_start;
  1649.     } 
  1650.     else 
  1651.       if (j && (i > 1 && !atoi(argv[i-2]))) 
  1652.         lowest = lowest_on_start;
  1653.   }
  1654.   
  1655.   return (lowest);
  1656.   
  1657. }
  1658.  
  1659. /*---------------------------------------------------------------------------*/
  1660.  
  1661. int get_highest_mesg(int argc, char **argv) {
  1662.  
  1663.   int i,j;
  1664.   int highest_index, highest=0;
  1665.   struct index index;
  1666.  
  1667.   if (lseek(fdindex, -sizeof(index), SEEK_END) < 0) return 0;
  1668.   if (read(fdindex, &index, sizeof(index)) != sizeof(struct index)) halt();
  1669.   highest_index = index.mesg+1;
  1670.   for (i = 1; i < argc; i++) {
  1671.     j=atoi(argv[i]);
  1672.     if (j) {
  1673.       if ((i < argc-1 && *argv[i+1] != '-') || i == argc-1) {
  1674.         if (j < highest_index) {
  1675.           if(j > highest) {
  1676.             highest = j;
  1677.           }
  1678.         }
  1679.       } 
  1680.       else {
  1681.         if (i < argc-2 && *argv[i+1] == '-' && !atoi(argv[i+2]) || 
  1682.             i == argc-2 && *argv[i+1] == '-') {
  1683.           highest = highest_index;
  1684.         }  
  1685.       }
  1686.     } 
  1687.     else { 
  1688.       if (*argv[i] == '+' && i < argc - 1 && atoi(argv[i+1])) {
  1689.         if (highest_index - atoi(argv[i+1]) > highest) {
  1690.            highest = highest_index - atoi(argv[i+1]);
  1691.         } 
  1692.       }
  1693.     } 
  1694.   }
  1695.   
  1696.   return (highest);
  1697.   
  1698. }
  1699.  
  1700. /*---------------------------------------------------------------------------*/
  1701.  
  1702. mesg_in_command(int argc, char **argv, int mesg, struct index *index)
  1703. {
  1704.   char *to = 0;
  1705.   int i, ok;
  1706.  
  1707.   if (!get_index(mesg,index)) return 0;
  1708.  
  1709.   for(i=1; i < argc; i++) 
  1710.     if(!atoi(argv[i]) && *argv[i] != '-') {
  1711.       to = argv[i];
  1712.       strcpy(last_board,to);
  1713.       strupc(last_board);
  1714.     }  
  1715.   if (interface_type != wampes && !to)
  1716.     to = last_board;
  1717.   
  1718.   for(i=1; i < argc; i++) {
  1719.     if (to) 
  1720.       if (Strcasecmp(to, index->to)) continue;
  1721.     if(mesg == atoi(argv[i])) 
  1722.           return 1;
  1723.     else {
  1724.       if (*argv[i] == '-' && !is_tell_user) {
  1725.         ok = 0;
  1726.         if (atoi(argv[i-1]))
  1727.           if(mesg > atoi(argv[i-1]))
  1728.               ok = 1;
  1729.           else
  1730.             continue;  
  1731.         if(i < argc-1 && atoi(argv[i+1]))
  1732.           if(mesg < atoi(argv[i+1]))
  1733.             ok = 1;
  1734.           else
  1735.             continue;
  1736.         if (ok) return 1;
  1737.       }      
  1738.     }       
  1739.   }
  1740.   return 0;
  1741. }
  1742.  
  1743. /*---------------------------------------------------------------------------*/
  1744.  
  1745. int get_highest_on_start(void)
  1746. {
  1747.   int i,j;
  1748.   struct index index;
  1749.  
  1750.   if (lseek(fdindex, -sizeof(index), SEEK_END) < 0) return 0;
  1751.   if (read(fdindex, &index, sizeof(index)) != sizeof(struct index)) halt();
  1752.  
  1753.   return (index.mesg);
  1754.  
  1755. }
  1756.  
  1757. /*---------------------------------------------------------------------------*/
  1758.  
  1759. int get_lowest_on_start(void)
  1760. {
  1761.  
  1762.   int i = 0;
  1763.   struct index index;
  1764.  
  1765.   while(get_index(i, &index) && (index.flags & DELETED)) i++;
  1766.  
  1767.   return (index.mesg);
  1768.  
  1769. }
  1770.  
  1771. /*---------------------------------------------------------------------------*/
  1772.  
  1773. void check_cmdaliases(char *line) 
  1774. {
  1775.  
  1776.   char buffer[2048];
  1777.   char cmd[256];
  1778.   char *f;
  1779.   char *t;
  1780.   struct aliastable *p;
  1781.  
  1782.   f=line;
  1783.   while(isspace(uchar(*f))) f++;
  1784.   t=f;
  1785.   while(isalpha(uchar(*t))) t++;
  1786.   if (t==f) return;
  1787.   strncpy(cmd,f,t-f); cmd[t-f]=0;
  1788.   strupc(cmd);
  1789.   p=alias_table;
  1790.   while (p) {
  1791.     if(!strncmp(cmd,p->orig,strlen(cmd)) && level >= p->level) {
  1792.       strcpy(buffer, p->alias);
  1793.       strcat(buffer,t);
  1794.       strcpy(line,buffer);
  1795.       if (!strncmp(cmd, p->alias,strlen(cmd))) return;      
  1796.       check_cmdaliases(line); 
  1797.       return;
  1798.     }
  1799.     p=p->next;
  1800.   }
  1801.   return;
  1802.   
  1803. }  
  1804.  
  1805. /*---------------------------------------------------------------------------*/
  1806.  
  1807. void connect_bbs(void)
  1808. {
  1809.  
  1810.   char *address;
  1811.   int addrlen;
  1812.   int fd;
  1813.   struct sockaddr *addr;
  1814.  
  1815.   if (!(address = connect_addr(user.name))) exit(1);
  1816.   if (!(addr = build_sockaddr("unix:/tcp/.sockets/netcmd", &addrlen))) exit(1);
  1817.   if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) exit(1);
  1818.   if (connect(fd, addr, addrlen)) exit(1);
  1819.   if (fd != 0) dup2(fd, 0);
  1820.   if (fd != 1) dup2(fd, 1);
  1821.   if (fd != 2) dup2(fd, 2);
  1822.   if (fd > 2) close(fd);
  1823.   fdopen(0, "r+");
  1824.   fdopen(1, "r+");
  1825.   fdopen(2, "r+");
  1826.   printf("connect %s\n", address);
  1827. }
  1828.  
  1829. /*---------------------------------------------------------------------------*/
  1830.  
  1831. void parse_command_line(char *line)
  1832. {
  1833.  
  1834. #define STARTDELIM      "#$<["
  1835. #define ANYDELIM        "@>]"
  1836. #define UANYDELIM    "=-+;"
  1837.  
  1838.   char *argv[256];
  1839.   char *f;
  1840.   char *t;
  1841.   char buf[2048];
  1842.   char delim[32];
  1843.   int argc;
  1844.   int len;
  1845.   int quote;
  1846.   const struct cmdtable *cmdp;
  1847.   
  1848.   FILE *dbfp;
  1849.   
  1850.  
  1851.   if (debug && (*line != '[')) {
  1852.     if ((fdlock = lock_file(LOCKFILE, 0)) < 0) halt();
  1853.     dbfp= fopen(debugfile,"a");
  1854.     fprintf(dbfp,"%s: %s\n",user.name, line);
  1855.     fclose(dbfp);
  1856.     close(fdlock);
  1857.   }
  1858.  
  1859.   if (!password_ok && (*line !=  '['))     return;
  1860.  
  1861.   if (level != MBOX) check_cmdaliases(line);
  1862.  
  1863.   strcpy(delim,ANYDELIM);
  1864.   if (level != MBOX) strcat(delim,UANYDELIM);
  1865.   f = line;
  1866.   do {
  1867.     argc = 0;
  1868.     memset((char *) argv, 0, sizeof(argv));  
  1869.     for (t = buf; ; ) {
  1870.       while (isspace(uchar(*f))) f++;
  1871.       if (!*f) break;
  1872.       if (level != MBOX && *f == ';') {
  1873.         f++;
  1874.         break;
  1875.       }  
  1876.       argv[argc++] = t;
  1877.       if (*f == '"' || *f == '\'') {
  1878.         quote = *f++;
  1879.         while (*f && *f != quote) *t++ = *f++;
  1880.         if (*f) f++;
  1881.       } else if (strchr(STARTDELIM,*f) || strchr(delim, *f)) {
  1882.         *t++ = *f++;
  1883.       } else {
  1884.         while (*f && !isspace(uchar(*f)) && !strchr(delim, *f)) *t++ = *f++;
  1885.       }
  1886.       *t++ = 0;
  1887.     }
  1888.     if (!argc) return;
  1889.     if (!(len = strlen(*argv))) return;
  1890.     for (cmdp = cmdtable; ; cmdp++)
  1891.       if (!cmdp->name ||
  1892.       level >= cmdp->level && !Strncasecmp(cmdp->name, *argv, len)) {
  1893.         if (argc >= cmdp->argc) {
  1894.       (*cmdp->fnc)(argc, argv);
  1895.       if (level != MBOX) printf("\n"); 
  1896.         }    
  1897.         else {
  1898.       errors++;
  1899.       if (level == MBOX)
  1900.         puts("NO");
  1901.       else  
  1902.         printf("The %s command requires more arguments.  Type ? %s for help.\n",
  1903.                cmdp->name, cmdp->name);
  1904.         }
  1905.         break;
  1906.       }
  1907.   } while(f);   
  1908.   if (level == MBOX && errors >= 3) exit(1);
  1909. }
  1910.  
  1911. /*---------------------------------------------------------------------------*/
  1912.  
  1913. char *connect_addr(char *host)
  1914. {
  1915.  
  1916.   FILE *fp;
  1917.   char *addr;
  1918.   static char line[1024];
  1919.   static char buf[80];
  1920.   char cmd[32];
  1921.   char *h, *p;
  1922.   int i;
  1923.  
  1924.   addr = 0;
  1925.   if (fp = fopen(CONFIGFILE, "r")) {
  1926.     while (fgets(line, sizeof(line), fp)) {
  1927.       *cmd=0;
  1928.       if (sscanf(line,"%s\n",cmd)) {
  1929.         if (*cmd != '#') {
  1930.           strlwc(cmd);
  1931.           if (!strncmp(cmd, "mbox",4)) {
  1932.             for (p = line+strlen(cmd); isspace(uchar(*p)); p++) ;
  1933.             for (h = p; *p && !isspace(uchar(*p)); p++) ;
  1934.             if (*p) *p++ = 0;
  1935.             if (!strcmp(h, host)) {
  1936.           addr = strtrim(p);
  1937.           break;
  1938.             }
  1939.           }
  1940.         }  
  1941.       }    
  1942.     }
  1943.     fclose(fp);
  1944.   }
  1945.   return addr;
  1946. }
  1947.  
  1948.  
  1949. int Atoi(char *str) 
  1950. {
  1951.   int i;
  1952.  
  1953.   for(i=0;i < strlen(str); i++)
  1954.     if (!isdigit(str[i])) return 0;
  1955.   
  1956.   return (atoi(str));
  1957.   
  1958. }
  1959.  
  1960.  
  1961. #ifdef TAYLOR103
  1962.  
  1963. int forward_mail() 
  1964. {
  1965.   struct filelist {
  1966.     struct filelist *next;
  1967.     char name[16];
  1968.   };
  1969.  
  1970.   DIR *dirp;
  1971.   FILE * fp;
  1972.   char bid[1024];
  1973.   char cfile[1024];
  1974.   char dfile[1024];
  1975.   char dirname[1024];
  1976.   char from[1024];
  1977.   char line[1024];
  1978.   char subject[1024];
  1979.   char tmp1[1024];
  1980.   char tmp2[1024];
  1981.   char to[1024];
  1982.   char xfile[1024];
  1983.   struct dirent *dp;
  1984.   struct filelist *filelist = 0;
  1985.   struct filelist *p;
  1986.   struct filelist *q;
  1987.   struct index index;
  1988.   struct stat statbuf;
  1989.   int count;
  1990.  
  1991.  
  1992.   sprintf(dirname, "/usr/spool/uucp/%s", user.name);
  1993.   if (dirp = opendir(dirname)) {
  1994.     for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
  1995.       if (*dp->d_name != 'C') continue;
  1996.       p = malloc(sizeof(*p));
  1997.       strcpy(p->name, dp->d_name);
  1998.       if (!filelist || strcmp(p->name, filelist->name) < 0) {
  1999.     p->next = filelist;
  2000.     filelist = p;
  2001.       } else {
  2002.     for (q = filelist; q->next && strcmp(p->name, q->next->name) > 0; q = q->next) ;
  2003.     p->next = q->next;
  2004.     q->next = p;
  2005.       }
  2006.     }
  2007.     closedir(dirp);
  2008.     for (; p = filelist; filelist = p->next, free(p)) {
  2009.       sprintf(cfile, "/usr/spool/uucp/%s/%s", user.name, p->name);
  2010.       if (!(fp = fopen(cfile, "r"))) continue;
  2011.       *dfile = *xfile = 0;
  2012.       while (fgets(line, sizeof(line), fp)) {
  2013.     if (*line == 'S' && sscanf(line, "%*s %*s %s %*s %*s %s", tmp1, tmp2) == 2 && *tmp1 == 'D')
  2014.       sprintf(dfile, "/usr/spool/uucp/%s/%s", user.name, tmp2);
  2015.     if (*line == 'S' && sscanf(line, "%*s %*s %s %*s %*s %s", tmp1, tmp2) == 2 && *tmp1 == 'X')
  2016.       sprintf(xfile, "/usr/spool/uucp/%s/%s", user.name, tmp2);
  2017.       }
  2018.       fclose(fp);
  2019.       if (!*dfile || !*xfile) continue;
  2020.       if (!(fp = fopen(xfile, "r"))) continue;
  2021.       *to = 0;
  2022.       while (fgets(line, sizeof(line), fp))
  2023.     if (!strncmp(line, "C rmail ", 8)) {
  2024.       sprintf(to, "%s!%s", user.name, line + 8);
  2025.       strtrim(to);
  2026.       break;
  2027.     }
  2028.       fclose(fp);
  2029.       if (!*to) continue;
  2030.       if (!(fp = fopen(dfile, "r"))) continue;
  2031.       *from = *subject = *bid = 0;
  2032.       if (fscanf(fp, "From %s", tmp1) == 1) {
  2033.     if (!strcmp(tmp1, "MAILER-DAEMON") || !strcmp(tmp1, "!"))
  2034.       strcpy(tmp1, myhostname);
  2035.     sprintf(from, "%s!%s", myhostname, tmp1);
  2036.     strtrim(from);
  2037.     while (fgets(line, sizeof(line), fp)) {
  2038.       if (*line == '\n') break;
  2039.       get_header_value("Subject:", 0, line, subject);
  2040.       get_header_value("Bulletin-ID:", 1, line, bid);
  2041.     }
  2042.       }
  2043.       fclose(fp);
  2044.       if (!*from) continue;
  2045.       if (stat(cfile, &statbuf)) continue;
  2046.       memset((char *) &index, 0, sizeof(index));
  2047.       index.date = statbuf.st_mtime;
  2048.       strncpy(index.bid, bid, LEN_BID);
  2049.       index.bid[LEN_BID] = 0;
  2050.       strupc(index.bid);
  2051.       strncpy(index.subject, subject, LEN_SUBJECT);
  2052.       index.subject[LEN_SUBJECT] = 0;
  2053.       strncpy(index.to, get_user_from_path(to), LEN_TO);
  2054.       index.to[LEN_TO] = 0;
  2055.       strupc(index.to);
  2056.       strcpy(index.orig_to,index.to);
  2057.       strncpy(index.at, get_host_from_path(to), LEN_AT);
  2058.       index.at[LEN_AT] = 0;
  2059.       strupc(index.at);      
  2060.       strcpy(_at, get_host_from_path(to));
  2061.       strupc(_at);
  2062.       strncpy(index.from, get_user_from_path(from), LEN_FROM);
  2063.       index.from[LEN_FROM] = 0;
  2064.       strupc(index.from);
  2065.       forward_message(&index, dfile, 1);
  2066.       if (unlink(cfile)) halt();
  2067.       if (unlink(dfile)) halt();
  2068.       if (unlink(xfile)) halt();
  2069.     }
  2070.   }
  2071.   return 0;
  2072. }
  2073.  
  2074. #endif
  2075.  
  2076. #ifdef TAYLOR104
  2077. int forward_mail()
  2078. {
  2079.   struct filelist {
  2080.     struct filelist *next;
  2081.     char name[16];
  2082.   };
  2083.  
  2084.   DIR *dirp;
  2085.   FILE * fp;
  2086.   char bid[1024];
  2087.   char cfile[1024];
  2088.   char dfile[1024];
  2089.   char dirname[1024];
  2090.   char from[1024];
  2091.   char line[1024];
  2092.   char subject[1024];
  2093.   char tmp1[1024];
  2094.   char tmp2[1024];
  2095.   char tmp3[1024];
  2096.   char to[1024];
  2097.   char xfile[1024];
  2098.   struct dirent *dp;
  2099.   struct filelist *filelist = 0;
  2100.   struct filelist *p;
  2101.   struct filelist *q;
  2102.   struct index index;
  2103.   struct stat statbuf;
  2104.  
  2105.   sprintf(dirname, "/usr/spool/uucp/%s", user.name);
  2106.   if (dirp = opendir(dirname)) {
  2107.     for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
  2108.       if (*dp->d_name != 'C') continue;
  2109.       p = malloc(sizeof(*p));
  2110.       strcpy(p->name, dp->d_name);
  2111.       if (!filelist || strcmp(p->name, filelist->name) < 0) {
  2112.     p->next = filelist;
  2113.     filelist = p;
  2114.       } else {
  2115.     for (q = filelist; q->next && strcmp(p->name, q->next->name) > 0; q = q->next) ;
  2116.     p->next = q->next;
  2117.     q->next = p;
  2118.       }
  2119.     }
  2120.     closedir(dirp);
  2121.     for (; p = filelist; filelist = p->next, free(p)) {
  2122.       sprintf(cfile, "/usr/spool/uucp/%s/%s", user.name, p->name);
  2123.       if (!(fp = fopen(cfile, "r"))) continue;
  2124.       *dfile = *xfile = *to = 0;
  2125.       while (fgets(line, sizeof(line), fp)) {
  2126.     if (*line == 'E' && sscanf(line, "%*s %*s %*s %*s %*s %s %*s %*s %*s %s %s", tmp1, tmp2, tmp3) == 3 && *tmp1 == 'D' && !strcmp(tmp2, "rmail")) {
  2127.       sprintf(dfile, "/usr/spool/uucp/%s/%s", user.name, tmp1);
  2128.       sprintf(to, "%s!%s", user.name, tmp3);
  2129.       strtrim(to);
  2130.     }
  2131.     if (*line == 'S' && sscanf(line, "%*s %*s %s %*s %*s %s", tmp1, tmp2) == 2 && *tmp1 == 'D')
  2132.       sprintf(dfile, "/usr/spool/uucp/%s/%s", user.name, tmp2);
  2133.     if (*line == 'S' && sscanf(line, "%*s %*s %s %*s %*s %s", tmp1, tmp2) == 2 && *tmp1 == 'X')
  2134.       sprintf(xfile, "/usr/spool/uucp/%s/%s", user.name, tmp2);
  2135.       }
  2136.       fclose(fp);
  2137.       if (!*dfile) continue;
  2138.       if (*xfile) {
  2139.     if (!(fp = fopen(xfile, "r"))) continue;
  2140.     while (fgets(line, sizeof(line), fp))
  2141.       if (!strncmp(line, "C rmail ", 8)) {
  2142.         sprintf(to, "%s!%s", user.name, line + 8);
  2143.         strtrim(to);
  2144.         break;
  2145.       }
  2146.     fclose(fp);
  2147.       }
  2148.       if (!*to) continue;
  2149.       if (!(fp = fopen(dfile, "r"))) continue;
  2150.       *from = *subject = *bid = 0;
  2151.       if (fscanf(fp, "From %s", tmp1) == 1) {
  2152.     if (!strcmp(tmp1, "MAILER-DAEMON") || !strcmp(tmp1, "!"))
  2153.       strcpy(tmp1, myhostname);
  2154.     sprintf(from, "%s!%s", myhostname, tmp1);
  2155.     strtrim(from);
  2156.     while (fgets(line, sizeof(line), fp)) {
  2157.       if (*line == '\n') break;
  2158.       get_header_value("Subject:", 0, line, subject);
  2159.       get_header_value("Bulletin-ID:", 1, line, bid);
  2160.     }
  2161.       }
  2162.       fclose(fp);
  2163.       if (!*from) continue;
  2164.       if (stat(cfile, &statbuf)) continue;
  2165.       memset((char *) &index, 0, sizeof(index));
  2166.       index.date = statbuf.st_mtime;
  2167.       strncpy(index.bid, bid, LEN_BID);
  2168.       index.bid[LEN_BID] = 0;
  2169.       strupc(index.bid);
  2170.       strncpy(index.subject, subject, LEN_SUBJECT);
  2171.       index.subject[LEN_SUBJECT] = 0;
  2172.       strncpy(index.to, get_user_from_path(to), LEN_TO);
  2173.       index.to[LEN_TO] = 0;
  2174.       strupc(index.to);
  2175.       strcpy(index.orig_to,index.to);
  2176.       strncpy(index.at, get_host_from_path(to), LEN_AT);
  2177.       index.at[LEN_AT] = 0;
  2178.       strupc(index.at);
  2179.       strncpy(index.from, get_user_from_path(from), LEN_FROM);
  2180.       index.from[LEN_FROM] = 0;
  2181.       strupc(index.from);
  2182.       forward_message(&index, dfile, strupc(get_host_from_path(to)), 1);
  2183.       if (unlink(cfile)) halt();
  2184.       if (unlink(dfile)) halt();
  2185.       if (*xfile && unlink(xfile)) halt();
  2186.     }
  2187.   }
  2188.   return 0;
  2189. }
  2190.  
  2191. #endif
  2192.  
  2193. /*---------------------------------------------------------------------------*/
  2194.  
  2195. int isvaliduser(char *s) {
  2196.  FILE *fp;
  2197.  char line[1024], buffer[1024];
  2198.  
  2199.   if (fp = fopen(mailfile, "r")) {
  2200.     while (fgets(line, sizeof(line), fp)) {
  2201.       *buffer=0;
  2202.       if (sscanf(line,"%s\n",buffer)) {
  2203.         if (*buffer != '#') {
  2204.           if(!strcmp(s, buffer)) {
  2205.             fclose(fp);
  2206.             return 1;
  2207.           }   
  2208.         }
  2209.       }
  2210.     }      
  2211.   }
  2212.   fclose(fp);
  2213.   return 0;  
  2214. }
  2215.  
  2216. /*---------------------------------------------------------------------------*/
  2217.  
  2218. int has_passwd(char *call) 
  2219. {
  2220.   FILE *fp;
  2221.   char filename[80];
  2222.   
  2223.   strcpy(filename,call);
  2224.   strcat(filename,".pwd");
  2225.   strlwc(filename);
  2226.   
  2227.   if ((fp=fopen(filename,"r")) == NULL)
  2228.      return(0);
  2229.      
  2230.   fclose(fp);
  2231.   return(1);
  2232.   
  2233. }
  2234.  
  2235. /*---------------------------------------------------------------------------*/
  2236.  
  2237. int get_passwd(char *call, char *timestamp, char *password)
  2238. {
  2239.   int  fd;
  2240.   char filename[80];
  2241.   int offset;
  2242.   int min, hour, day;
  2243.   char buf[1024];
  2244.   int i;
  2245.  
  2246.   
  2247.   strcpy(filename,call);
  2248.   strcat(filename,".pwd");
  2249.   strlwc(filename);
  2250.  
  2251.   if ((fd=open(filename,O_RDONLY)) == -1)
  2252.      return(0);
  2253.  
  2254.   if (strlen(timestamp) != 10) return 0;
  2255.  
  2256.   strncpy(buf, timestamp, 2); buf[2] = '\0';
  2257.   day = atoi(buf);
  2258.   strncpy(buf, ×tamp[6], 2); buf[2] = '\0';
  2259.   hour = atoi(buf);
  2260.   strncpy(buf, ×tamp[8], 2); buf[2] = '\0';
  2261.   min = atoi(buf);
  2262.  
  2263.   offset = ((min + day) % 60) * 27 + hour;
  2264.  
  2265.   if (hour > 23) halt();
  2266.  
  2267.   if(lseek(fd, (long) (offset), SEEK_SET) == -1) halt();
  2268.   
  2269.   if(read(fd, password, 4) < 1) halt();
  2270.   
  2271.   password[4] = '\0';
  2272.   
  2273.   close(fd);
  2274.  
  2275.   return 1;
  2276. }
  2277.  
  2278.  
  2279.  
  2280. /*---------------------------------------------------------------------------*/
  2281.  
  2282.